package com.example.utils;

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangs
 * @version v1.0
 * @decription CountDownLatch的使用
 * @date 2021/3/30 23:11
 **/
public class CountDownLatchDemo {
    // 事件回调接口
    @FunctionalInterface
    interface Action {
        void action();
    }

    static class Task1 extends Thread {
        // 事件回调，在任务完成后调用
        private Action action;

        public Task1(Action action) {
            this.action = action;
        }

        @Override
        public void run() {
            try {
                System.out.println(getName() + "开始加载配置文件！");
                TimeUnit.SECONDS.sleep(2);
                System.out.println(getName() + "配置文件加载成功！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                action.action();
            }
        }
    }

    static class Task2 extends Thread {
        // 事件回调，在任务完成后调用
        private Action action;

        public Task2(Action action) {
            this.action = action;
        }

        @Override
        public void run() {
            try {
                System.out.println(getName() + "开始加载配置文件！");
                TimeUnit.SECONDS.sleep(3);
                System.out.println(getName() + "配置文件加载成功！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 任务完成之后的回调
                action.action();
            }
        }
    }

    private static void joinForWait() throws InterruptedException {
        // 使用Thread.join()
        Task1 task1 = new Task1(() -> {
            System.out.println("Task1任务完成时间：" + new Date());
        });
        Task2 task2 = new Task2(() -> {
            System.out.println("Task2任务完成时间：" + new Date());
        });

        task1.start();
        task2.start();

        // 使用Thread.join()暂停主线程
        task1.join();
        task2.join();
    }

    private static void countDownLatchForWait() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(2);
        // 创建任务并传入回调
        Task1 task1 = new Task1(() -> {
            System.out.println("Task1任务完成时间：" + new Date());
            // 任务完成，需要等待的线程减一
            cdl.countDown();
        });
        Task2 task2 = new Task2(() -> {
            System.out.println("Task2任务完成时间：" + new Date());
            cdl.countDown();
        });

        task1.start();
        task2.start();

        // 主线程等待任务完成
        cdl.await();
    }

    public static void main(String[] args) throws InterruptedException {
        // 使用wait方法等待线程完成
        joinForWait();

        // 使用CountDownLatch
        countDownLatchForWait();
    }
}
